library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity shifter is
  generic( N       :     natural := 32;
           N_SHAMT :     natural := 5 );
  port( ARITH      : in  std_logic;     -- '1' means arithmetic shift, '0' means logIcal shift
        DIR        : in  std_logic;     -- '0' means left shift, '1' means right shift
        ROT        : in  std_logic;     -- '1' means rotation, '0' means simple shift
        D_IN       : in  std_logic_vector (N-1 downto 0);
        SHAMT      : in  std_logic_vector (N_SHAMT-1 downto 0);
        D_OUT      : out std_logic_vector (N-1 downto 0)
        );
end shifter;

architecture Behavioral of shifter is
  signal amt : natural range 0 to N-1;
begin
  amt <= to_integer(unsigned(SHAMT));

  process (D_IN, amt, ARITH, DIR, ROT)
  begin
    if DIR = '0' then                   --left shift    
      for i in N - 1 downto 0 loop
        if i >= amt then
          D_OUT (i)   <= D_IN(i-amt);
        else
          -- if ROT='0' all zeros are inserted from right both for arithmetic and logical shift
          D_OUT (i)   <= D_IN(i+N-amt) and ROT;
        end if;
      end loop;
    else                                --right shift
      for i in 0 to N-1 loop
        if i          <= (N-1-amt) then
          D_OUT (i)   <= D_IN(i+amt);
        else
          if ROT = '0' then             --simple shift
                                        -- if ARITH='1' the sign extension is done, otherwise all zeros are inserted from the left
            D_OUT (i) <= D_IN(N-1) and ARITH;
          else                          --rotate
            D_OUT (i) <= D_IN(i+amt-N);				-- bits rotation			
          end if;
        end if;
      end loop;
    end if; -- end DIR

  end process;

end Behavioral;
